/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			module.h
  \date			Dec 2011
  \author		TNick

  \brief		Contains the definition for Module class


*//*

 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Please read COPYING and README files in root folder
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
#ifndef __MODULE_INC__
#define __MODULE_INC__
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<QString>
#include	<QList>

/*  INCLUDES    ============================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */


namespace	PgSave	{
class	IPgSave;
}

namespace	PgScr	{

class	UserVar;
class	UserFunc;
struct	Session;

/**
*	@brief	 class representing a logical module
*
*
*/
class Module				{

	//
	//
	//
	//
	/*  DEFINITIONS    ----------------------------------------------------- */

#ifdef	PGSCRIPT_TESTS
	friend void		Module_Tests	( int&, int& );
#endif

	/*  DEFINITIONS    ===================================================== */
	//
	//
	//
	//
	/*  DATA    ------------------------------------------------------------ */


protected:

	/**
	*	@brief	 parent session
	*/
	Session	*					prnt_ss;


	/**
	*	@brief	 list of build-in variables
	*/
	UserVar *					bld_in_var;
	/**
	*	@brief	 number of build-in variables in table pointed by \b bld_in_var
	*/
	int							bld_in_var_cnt;


	/**
	*	@brief	 list of build-in variables
	*/
	UserFunc *					bld_in_fun;


	/**
	*	@brief	 number of build-in variables in table pointed by \b bld_in_var
	*/
	int							bld_in_fun_cnt;


	/**
	*	@brief	 the name of this module
	*/
	QString						name_;


private:


	/**
	*	@brief	 the list of user defined variables
	*/
	QList<UserVar*>				usr_var_;



	/**
	*	@brief	 the list of user defined variables
	*/
	QList<UserFunc*>			usr_fun_;




	/*  DATA    ============================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ------------------------------------------------------- */

public:

	/**
	*	@brief	 constructor;
	*/
	Module				( QString md_name );

	/**
	*	@brief	 constructor;
	*/
	Module				( QString md_name, Session * parent_ss );


	/**
	*	@brief	 destructor;
	*/
	virtual				~Module			( void );



	/**
	*	@brief	 get the name of this module
	*/
	inline QString		name			( void ) const
	{ return name_; }

protected:

	/**
	*	@brief	 set / change the name of the module
	*/
	inline void			setName			( QString new_val )
	{ name_ = new_val; }


public:

	/**
	*	@brief	 report the session that contains this module
	*/
	inline Session*		session			( void )
	{ return prnt_ss; }


	/**
	*	@brief	loads a module from provided interface
	*
	*	The interface is assumed to have the current path set to the folder
	*	that contains the module; the function will enter the module folder
	*	itself
	*
	*	The method loads the saved state of existing build-in variables and
	*	creates / updates the user deined ones. loadFull(), on the otehr hand,
	*	will load entire state including the build-in variables from thin air.
	*
	*	@param	targ_i	the interface to use
	*/
	void				load				(
			PgSave::IPgSave& targ_i
			);


	/**
	*	@brief	loads a module from provided interface
	*
	*	The interface is assumed to have the current path set to the folder
	*	that contains the module; the function will enter the module folder
	*	itself
	*
	*	This method creates everything including build in variables. load(), on
	*	the other hand, will get existing build-in variables and dynamically
	*	load only user-defined ones.
	*
	*	@param	targ_i	the interface to use
	*/
	void				loadFull				(
			PgSave::IPgSave& targ_i
			);

	/**
	*	@brief	saves a module to provided interface
	*
	*	The interface is assumed to have the current path set to the folder
	*	that will contain the module; the function will create the
	*	folder and save things
	*
	*	@param	targ_i	the interface to use
	*/
	void			save					(
			PgSave::IPgSave& targ_i
			);







public:

	/**
	*	@brief	loads a module from provided interface
	*
	*	the interface is assumed to have the current path set to the folder
	*	that contains the module; the function will enter the module folder
	*	itself
	*
	*	Once the instance is created it uses standard loadFull() to populate
	*	the module.
	*
	*	@param	s_name		the name of the module
	*	@param	targ_ses	where to append this module
	*	@param	targ_i		the interface to use
	*
	*	@return		NULL if failure, the pointer to newly created module
	*/
	static Module *		loadFull					(
			QString				s_name,
			Session *			targ_ses,
			PgSave::IPgSave& targ_i
			);




	/**
	*	@brief	 get the module at index i
	*/
	static Module*		module			( Session * ss, int i );


	/**
	*	@brief	 get the module at index i
	*/
	static Module*		module			( int i );



	/**
	*	@brief	 get the index for a module (-1 if not inhere)
	*/
	static int			module			( Session * ss, Module * md );


	/**
	*	@brief	 get the index for a module (-1 if not inhere)
	*/
	static int			module			( Module * md );



	/**
	*	@brief	 get the module with name \b m_name
	*/
	/**
	  *	The string will not be trimmed and is expected to be already uppercase
	  */
	static Module*		module			( Session * ss, QString m_name );


	/**
	*	@brief	 get the module with name \b m_name
	*
	*	The string will not be trimmed and is expected to be already uppercase
	*/
	static Module*		module			( QString m_name );




	/**
	*	@brief	 tell if a module is the core module
	*/
	static bool			isCoreModule	( Module * md );


	/**
	*	@brief add a module to the list of core modules
	*/
	static void			addCoreModule	( Module * md );


	/**
	*	@brief remove a module from the list of core modules
	*/
	static void			remCoreModule	( Module * md );





	//	/** @name Variables
	//	  *	Variables are class intances that inherit from UserVar. The application
	//	  *	stores global variables in App class and local variables in working units and
	//	  *	modules.
	//	  *
	//	  *	The two types of variables (user defined and build-in) are stored
	//	  *	separatelly, as the build-in are not variable over time while
	//	  *	the user defined ones may be added / deleted. The interface, however,
	//	  *	this detail, providing unified interaction. To differentiate
	//	  *	between build-in and user-defined variables use UserVar::isPredef().
	//	  *
	//	  *	Build-in variables are saved by default. User-defined variables
	//	  *	must be marked for saving.
	//	  *
	//	  */
	//	//@{

	//	/**
	//	*	@brief	 find a variable inside this module
	//	*/
	//	/**
	//	  *	The string is expected to be trimmed and uppercase. Both build-in
	//	  *	and user defined variables are searched. Also, the module specifier
	//	  *	and coresponding dot should be removed prior to the call.
	//	  *
	//	  *	@return if the variable is found a pointer to it is returned,
	//	  *	otherwise NULL
	//	  */
	//	UserVar *			findVariable			( const QString & var_n );

	//	/**
	//	*	@brief	 add a new user-defined variable at module level
	//	*/
	//	/**
	//	  *	the other variables are querried for their names and, if a conflict
	//	  *	is found, the function will not append the variable.
	//	  *
	//	  *	@return true if the variable was appended
	//	  */
	//	bool				appendVar				( UserVar * var_inst );

	//	/**
	//	*	@brief	 remove a user-defined variable at module level
	//	*/
	//	/**
	//	  *	if the variable is not found to be part of the user defined variables
	//	  *	from global level false is returned. Note that the function does NOT
	//	  *	delete the instance from memory, it only extracts it from chain.
	//	  *
	//	  *	@return true if the variable was extracted from the chain
	//	  */
	//	bool				removeVar				( UserVar * var_inst );

	//	/**
	//	*	@brief	 remove a user-defined variable at module level
	//	*/
	//	/**
	//	  *	The string is expected to be trimmed and uppercase. The module specifier
	//	  *	and coresponding dot should be removed prior to the call.
	//	  *
	//	  *	@return true if found and removed, false if not found
	//	  */
	//	bool				removeVar				( const QString & s_name );


	//	//@}



	//	/** @name Functions
	//	  *	Functions are class intances that inherit from UserFunc. The application
	//	  *	stores global functions in App class and local functions in working units and
	//	  *	modules.
	//	  *
	//	  *	The two types of functions (user defined and build-in) are stored
	//	  *	separatelly, as the build-in are not changing over time while
	//	  *	the user defined ones may be added / deleted. The interface, however,
	//	  * hides this detail, providing unified interaction. To differentiate
	//	  *	between build-in and user-defined functions use UserFunc::isPredef().
	//	  *
	//	  *	Build-in functions need no saving. User-defined functions
	//	  *	must be marked for saving.
	//	  */
	//	//@{


	//	/**
	//	*	@brief	 find a function by it's name inside this module
	//	*/
	//	/**
	//	  *	The string is expected to be trimmed and uppercase. Both build-in
	//	  *	and user defined functions are searched. Also, the module specifier
	//	  *	and coresponding dot should be removed prior to the call.
	//	  *
	//	  *	@return if the function is found a pointer to it is returned,
	//	  *	otherwise NULL
	//	  */
	//	UserFunc *			findFunction			( const QString & var_n );


	//	/**
	//	*	@brief	 add a new user-defined function at global level
	//	*/
	//	/**
	//	  *	the other functions are querried for their names and, if a conflict
	//	  *	is found, the method will not append the function.
	//	  *
	//	  *	@return true if the function was appended
	//	  */
	//	bool				appendFun				( UserFunc * var_inst );


	//	/**
	//	*	@brief	 remove a user-defined function at global level
	//	*/
	//	/**
	//	  *	if the function is not found to be part of the user defined functions
	//	  *	from global level false is returned. Note that the method does NOT
	//	  *	delete the instance from memory, it only extracts it from chain.
	//	  *
	//	  *	@return true if the function was extracted from the chain
	//	  */
	//	bool				removeFun				( UserFunc * var_inst );


	//	/**
	//	*	@brief	 remove a user-defined function at global level
	//	*/
	//	/**
	//	  *	The string is expected to be trimmed and uppercase. The module specifier
	//	  *	and coresponding dot should be removed prior to the call.
	//	  *
	//	  *	@return true if found and removed, false if not found
	//	  */
	//	bool				removeFun				( const QString & s_name );


	//	//@}








	/*  FUNCTIONS    ======================================================= */
	//
	//
	//
	//

};	/*	class Module	*/

/*  CLASS    =============================================================== */
//
//
//
//

void				Module_Tests					(
		int & performed,
		int & succeded
		);

}	//	namespace	PgScr

#endif // __MODULE_INC__
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
